home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume2
/
editors
/
stevie.1
< prev
next >
Wrap
Text File
|
1988-12-02
|
60KB
|
2,627 lines
Path: xanth!mcnc!gatech!bloom-beacon!mit-eddie!ll-xn!adelie!infinet!ulowell!page
From: page@swan.ulowell.edu (Bob Page)
Newsgroups: comp.sources.amiga
Subject: v02i081: stevie - vi editor clone, Part01/04
Message-ID: <10419@swan.ulowell.edu>
Date: 2 Dec 88 01:42:33 GMT
Organization: University of Lowell, Computer Science Dept.
Lines: 2616
Approved: page@swan.ulowell.edu
Submitted-by: grwalter@watcgl.waterloo.edu
Posting-number: Volume 2, Issue 81
Archive-name: editors/stevie.1
This is a source release of the STEVIE editor, a public domain clone
of the UNIX editor 'vi'. The program was originally developed for the
Atari ST, but has been ported to UNIX, OS/2, BSD 4.3 and the Amiga.
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# Makefile
# README
# alloc.c
# amiga.c
# amiga.h
# ascii.h
# charset.c
# cmdline.c
# dec.c
# edit.c
# fileio.c
# help.c
# inc.c
# This archive created: Thu Dec 1 20:37:03 1988
cat << \SHAR_EOF > Makefile
#
# Makefile for Lattice C on Amiga
#
.c.o:
lc $(CFLAGS) $<
LIBS = /regexp/regexp.lib
LDFLAGS=
CFLAGS = -cu -dAUTO_INDENT
LINKFLAGS = NODEBUG
MACH= amiga.o raw.o sendpacket.o
OBJ= main.o edit.o linefunc.o normal.o cmdline.o charset.o \
updateRealscreen.o misccmds.o help.o dec.o inc.o search.o alloc.o \
updateNextscreen.o mark.o screen.o fileio.o param.o $(MACH)
all : stevie
stevie : $(OBJ)
BLINK TO stevie FROM lib:c.o $(OBJ) \
LIBRARY $(LIBS) lib:lc.lib lib:amiga.lib \
$(LINKFLAGS)
clean :
delete $(OBJ)
SHAR_EOF
cat << \SHAR_EOF > README
STEVIE Source Release
This is a source release of the STEVIE editor, a public domain clone
of the UNIX editor 'vi'. The program was originally developed for the
Atari ST, but has been ported to UNIX, OS/2, BSD 4.3 and the Amiga as well.
To compile STEVIE, you'll also need Henry Spencer's regular expression
library.
The files included in this release are:
README
This file.
stevie.doc
Reference manual for STEVIE. Assumes familiarity with vi.
source.doc
Quick overview of the major data structures used.
porting.doc
Tips for porting STEVIE to other systems.
makefile.os2
makefile.usg
makefile.tos
makefile.bsd
makefile.amiga.lattice
Makefiles for OS/2, UNIX System V, Atari ST, BSD 4.3 UNIX and the
Amiga respectively.
amiga.c
amiga.h
bsd.c
bsd.h
os2.c
os2.h
unix.c
unix.h
tos.c
tos.h
System-dependent routines for the same.
alloc.c ascii.h cmdline.c edit.c fileio.c help.c charset.c
keymap.h linefunc.c main.c mark.c misccmds.c normal.c param.c
param.h ptrfunc.c screen.c search.c stevie.h term.h macros.h
C source and header files for STEVIE.
To compile STEVIE for one of the provided systems:
1. Compile the regular expression library and install as
appropriate for your system.
2. Edit the file 'stevie.h' to set the system defines as needed.
3. Check the makefile for your system, and modify as needed.
4. Compile.
Good Luck...
Tony Andrews March 12, 1988
G. R. (Fred) Walter August 14, 1988
SHAR_EOF
cat << \SHAR_EOF > alloc.c
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
#include "stevie.h"
/*
* This file contains various routines dealing with allocation and
* deallocation of data structures.
*/
char *
alloc(size)
unsigned size;
{
char *p; /* pointer to new storage space */
p = malloc(size);
if (p == (char *) NULL) { /* if there is no more room... */
emsg("alloc() is unable to find memory!");
}
return (p);
}
char *
strsave(string)
char *string;
{
return (strcpy(alloc((unsigned) (strlen(string) + 1)), string));
}
void
screenalloc()
{
/*
* If we're changing the size of the screen, free the old arrays
*/
if (Realscreen != NULL)
free(Realscreen);
if (Nextscreen != NULL)
free(Nextscreen);
Realscreen = malloc((unsigned) (Rows * Columns));
Nextscreen = malloc((unsigned) (Rows * Columns));
}
/*
* Allocate and initialize a new line structure with room for 'nchars'
* characters.
*/
LINE *
newline(nchars)
int nchars;
{
LINE *l;
l = (LINE *) alloc((unsigned) sizeof(LINE));
if (l == NULL)
return (LINE *) NULL;
l->s = alloc((unsigned) nchars); /* the line is empty */
l->s[0] = NUL;
l->size = nchars;
l->prev = (LINE *) NULL; /* should be initialized by caller */
l->next = (LINE *) NULL;
return l;
}
/*
* filealloc() - construct an initial empty file buffer
*/
void
filealloc()
{
if ((Filemem->linep = newline(1)) == NULL) {
fprintf(stderr, "Unable to allocate file memory!\n");
getout(1);
}
if ((Fileend->linep = newline(1)) == NULL) {
fprintf(stderr, "Unable to allocate file memory!\n");
getout(1);
}
Filemem->index = 0;
Fileend->index = 0;
Filemem->linep->next = Fileend->linep;
Fileend->linep->prev = Filemem->linep;
*Curschar = *Filemem;
*Topchar = *Filemem;
Filemem->linep->num = 0;
Fileend->linep->num = 0xffff;
clrall(); /* clear all marks */
}
/*
* freeall() - free the current buffer
*
* Free all lines in the current buffer.
*/
void
freeall()
{
LINE *lp, *xlp;
for (lp = Filemem->linep; lp != NULL; lp = xlp) {
if (lp->s != NULL)
free(lp->s);
xlp = lp->next;
free((char *) lp);
}
Curschar->linep = NULL; /* clear pointers */
Filemem->linep = NULL;
Fileend->linep = NULL;
}
/*
* canincrease(n) - returns TRUE if the current line can be increased 'n'
* bytes
*
* This routine returns immediately if the requested space is available. If not,
* it attempts to allocate the space and adjust the data structures
* accordingly. If everything fails it returns FALSE.
*/
bool_t
canincrease(n)
int n;
{
int nsize;
char *s; /* pointer to new space */
nsize = strlen(Curschar->linep->s) + 1 + n; /* size required */
if (nsize <= Curschar->linep->size)
return TRUE;
/*
* Need to allocate more space for the string. Allow some extra space on
* the assumption that we may need it soon. This avoids excessive numbers
* of calls to malloc while entering new text.
*/
s = alloc((unsigned) (nsize + SLOP));
if (s == NULL) {
emsg("Can't add anything, file is too big!");
State = NORMAL;
return FALSE;
}
Curschar->linep->size = nsize + SLOP;
strcpy(s, Curschar->linep->s);
free(Curschar->linep->s);
Curschar->linep->s = s;
return TRUE;
}
SHAR_EOF
cat << \SHAR_EOF > amiga.c
/*
* Amiga system-dependent routines.
*/
#include "stevie.h"
long stdin_file_handle = 0;
int
GetCharacter()
{
char c;
Read(stdin_file_handle, &c, sizeof(c));
return ((int) c);
}
/*
* getCSIsequence - get a CSI sequence
* - either cursor keys, help, functionkeys, or some
* other sequence (if other, check window size)
*/
int
getCSIsequence()
{
int c;
int param1;
int param2;
c = GetCharacter();
if (isdigit(c)) {
param1 = 0;
while (isdigit(c)) {
param1 = param1 * 10 + c - '0';
c = GetCharacter();
}
if (c == '~') /* function key */
return ((char) (K_F1 + param1));
/* must be an event of some sort or a window bound report */
if (c == ';') {
param2 = 0;
c = GetCharacter();
while (isdigit(c)) {
param2 = param2 * 10 + c - '0';
c = GetCharacter();
}
if (c == ';') {
param1 = 0;
c = GetCharacter();
while (isdigit(c)) {
param1 = param1 * 10 + c - '0';
c = GetCharacter();
}
if (c == ';') {
param2 = 0;
c = GetCharacter();
while (isdigit(c)) {
param2 = param2 * 10 + c - '0';
c = GetCharacter();
}
if (c == ' ') {
c = GetCharacter();
if (c == 'r') {
if (param1 < 2)
param1 = 2;
if (param2 < 5)
param2 = 5;
if (Columns != param2 || Rows != param1) {
Columns = param2;
Rows = param1;
P(P_LI) = Rows;
return (-1);
} else
return 0;
}
}
}
}
}
while ((c != '|') && (c != '~'))
c = GetCharacter();
outstr("\033[0 q");
fflush(stdout); /* flush out the window size request */
return 0;
}
switch (c) {
case 'A': /* cursor up */
return K_UARROW;
case 'B': /* cursor down */
return K_DARROW;
case 'C': /* cursor right */
return K_RARROW;
case 'D': /* cursor left */
return K_LARROW;
case 'T': /* shift cursor up */
return K_SUARROW;
case 'S': /* shift cursor down */
return K_SDARROW;
case ' ': /* shift cursor left or right */
c = GetCharacter();
if (c == 'A') /* shift cursor left */
return K_SLARROW;
if (c == '@') /* shift cursor right */
return K_SRARROW;
break;
case '?': /* help */
c = GetCharacter();
if (c == '~')
return K_HELP;
break;
}
return 0; /* some other control code */
}
/*
* inchar() - get a character from the keyboard
*/
char
inchar()
{
int c;
fflush(stdout); /* flush any pending output */
for (;;) {
c = GetCharacter();
if (c != 0x9b)
break;
c = getCSIsequence();
if (c > 0)
break;
if (c == -1) {
screenalloc();
screenclear();
updateNextscreen();
updateRealscreen();
msg("");
cursupdate();
windgoto(Cursrow, Curscol);
fflush(stdout);
}
}
return (char) c;
}
void
outstr(s)
char *s;
{
while (*s)
outchar(*s++);
}
void
beep()
{
if (RedrawingDisabled)
return;
outchar('\007');
}
void
sleep(n)
int n;
{
void Delay();
if (n > 0)
Delay(50L * n);
}
void
delay()
{
void Delay();
Delay(25L);
}
void
windinit()
{
stdin_file_handle = Input();
if (!IsInteractive(stdin_file_handle)) {
fprintf(stderr, "stdin is not interactive ?!?!?!?");
exit(2);
}
Columns = 80;
P(P_LI) = Rows = 24;
if (raw(stdin) != 0)
perror("raw");
outstr("\033[12{"); /* window resize events activated */
outstr("\033[0 q"); /* get window size */
fflush(stdout);
for (;;) {
if (GetCharacter() == 0x9b)
if (getCSIsequence() == -1)
break;
}
}
void
windexit(r)
int r;
{
outstr("\033[12}"); /* window resize events de-activated */
fflush(stdout); /* flush any pending output */
if (cooked(stdin) != 0)
perror("cooked");
exit(r);
}
void
windgoto(r, c)
int c;
int r;
{
r++;
c++;
outstr("\033[");
if (r >= 10)
outchar((char) (r / 10 + '0'));
outchar((char) (r % 10 + '0'));
outchar(';');
if (c >= 10)
outchar((char) (c / 10 + '0'));
outchar((char) (c % 10 + '0'));
outchar('H');
}
FILE *
fopenb(fname, mode)
char *fname;
char *mode;
{
FILE *fopen();
char modestr[16];
sprintf(modestr, "%sb", mode);
return fopen(fname, modestr);
}
SHAR_EOF
cat << \SHAR_EOF > amiga.h
/*
* Amiga Machine-dependent routines.
*/
char inchar();
#define outchar(c) putchar(c)
void outstr();
void beep();
void windinit(), windexit(), windgoto();
void delay();
void sleep();
SHAR_EOF
cat << \SHAR_EOF > ascii.h
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
/*
* Definitions of various common control characters
*/
#define NUL '\000'
#define BS '\010'
#define TAB '\011'
#define NL '\012'
#define NL_STR "\012"
#define CR '\015'
#define ESC '\033'
#define ESC_STR "\033"
#define UNDO_SHIFTJ '\333'
#define UNDO_SHIFTJ_STR "\333"
#define CTRL(x) ((x) & 0x1f)
SHAR_EOF
cat << \SHAR_EOF > charset.c
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
#include "stevie.h"
/*
* This file shows how to display characters on the screen. This is approach
* is something of an overkill. It's a remnant from the original code that
* isn't worth messing with for now. TABS are special-cased depending on the
* value of the "list" parameter.
*/
struct charinfo chars[] = {
/* 0 */ 1, NUL,
/* 1 */ 2, "^A",
/* 2 */ 2, "^B",
/* 3 */ 2, "^C",
/* 4 */ 2, "^D",
/* 5 */ 2, "^E",
/* 6 */ 2, "^F",
/* 7 */ 2, "^G",
/* 8 */ 2, "^H",
/* 9 */ 2, "^I",
/* 10 */ 7, "[ERROR]", /* shouldn't happen */
/* 11 */ 2, "^K",
/* 12 */ 2, "^L",
/* 13 */ 2, "^M",
/* 14 */ 2, "^N",
/* 15 */ 2, "^O",
/* 16 */ 2, "^P",
/* 17 */ 2, "^Q",
/* 18 */ 2, "^R",
/* 19 */ 2, "^S",
/* 20 */ 2, "^T",
/* 21 */ 2, "^U",
/* 22 */ 2, "^V",
/* 23 */ 2, "^W",
/* 24 */ 2, "^X",
/* 25 */ 2, "^Y",
/* 26 */ 2, "^Z",
/* 27 */ 2, "^[",
/* 28 */ 2, "^\\",
/* 29 */ 2, "^]",
/* 30 */ 2, "^^",
/* 31 */ 2, "^_",
/* 32 */ 1, " ",
/* 33 */ 1, "!",
/* 34 */ 1, "\"",
/* 35 */ 1, "#",
/* 36 */ 1, "$",
/* 37 */ 1, "%",
/* 38 */ 1, "&",
/* 39 */ 1, "'",
/* 40 */ 1, "(",
/* 41 */ 1, ")",
/* 42 */ 1, "*",
/* 43 */ 1, "+",
/* 44 */ 1, ",",
/* 45 */ 1, "-",
/* 46 */ 1, ".",
/* 47 */ 1, "/",
/* 48 */ 1, "0",
/* 49 */ 1, "1",
/* 50 */ 1, "2",
/* 51 */ 1, "3",
/* 52 */ 1, "4",
/* 53 */ 1, "5",
/* 54 */ 1, "6",
/* 55 */ 1, "7",
/* 56 */ 1, "8",
/* 57 */ 1, "9",
/* 58 */ 1, ":",
/* 59 */ 1, ";",
/* 60 */ 1, "<",
/* 61 */ 1, "=",
/* 62 */ 1, ">",
/* 63 */ 1, "?",
/* 64 */ 1, "@",
/* 65 */ 1, "A",
/* 66 */ 1, "B",
/* 67 */ 1, "C",
/* 68 */ 1, "D",
/* 69 */ 1, "E",
/* 70 */ 1, "F",
/* 71 */ 1, "G",
/* 72 */ 1, "H",
/* 73 */ 1, "I",
/* 74 */ 1, "J",
/* 75 */ 1, "K",
/* 76 */ 1, "L",
/* 77 */ 1, "M",
/* 78 */ 1, "N",
/* 79 */ 1, "O",
/* 80 */ 1, "P",
/* 81 */ 1, "Q",
/* 82 */ 1, "R",
/* 83 */ 1, "S",
/* 84 */ 1, "T",
/* 85 */ 1, "U",
/* 86 */ 1, "V",
/* 87 */ 1, "W",
/* 88 */ 1, "X",
/* 89 */ 1, "Y",
/* 90 */ 1, "Z",
/* 91 */ 1, "[",
/* 92 */ 1, "\\",
/* 93 */ 1, "]",
/* 94 */ 1, "^",
/* 95 */ 1, "_",
/* 96 */ 1, "`",
/* 97 */ 1, "a",
/* 98 */ 1, "b",
/* 99 */ 1, "c",
/* 100 */ 1, "d",
/* 101 */ 1, "e",
/* 102 */ 1, "f",
/* 103 */ 1, "g",
/* 104 */ 1, "h",
/* 105 */ 1, "i",
/* 106 */ 1, "j",
/* 107 */ 1, "k",
/* 108 */ 1, "l",
/* 109 */ 1, "m",
/* 110 */ 1, "n",
/* 111 */ 1, "o",
/* 112 */ 1, "p",
/* 113 */ 1, "q",
/* 114 */ 1, "r",
/* 115 */ 1, "s",
/* 116 */ 1, "t",
/* 117 */ 1, "u",
/* 118 */ 1, "v",
/* 119 */ 1, "w",
/* 120 */ 1, "x",
/* 121 */ 1, "y",
/* 122 */ 1, "z",
/* 123 */ 1, "{",
/* 124 */ 1, "|",
/* 125 */ 1, "}",
/* 126 */ 1, "~",
/* 127 */ 2, "^?",
/* 128 */ 5, "[128]",
/* 129 */ 5, "[129]",
/* 130 */ 5, "[130]",
/* 131 */ 5, "[131]",
/* 132 */ 5, "[132]",
/* 133 */ 5, "[133]",
/* 134 */ 5, "[134]",
/* 135 */ 5, "[135]",
/* 136 */ 5, "[136]",
/* 137 */ 5, "[137]",
/* 138 */ 5, "[138]",
/* 139 */ 5, "[139]",
/* 140 */ 5, "[140]",
/* 141 */ 5, "[141]",
/* 142 */ 5, "[142]",
/* 143 */ 5, "[143]",
/* 144 */ 5, "[144]",
/* 145 */ 5, "[145]",
/* 146 */ 5, "[146]",
/* 147 */ 5, "[147]",
/* 148 */ 5, "[148]",
/* 149 */ 5, "[149]",
/* 150 */ 5, "[150]",
/* 151 */ 5, "[151]",
/* 152 */ 5, "[152]",
/* 153 */ 5, "[153]",
/* 154 */ 5, "[154]",
/* 155 */ 5, "[155]",
/* 156 */ 5, "[156]",
/* 157 */ 5, "[157]",
/* 158 */ 5, "[158]",
/* 159 */ 5, "[159]",
#ifdef AMIGA
/* 160 */ 1, "\240",
/* 161 */ 1, "\241",
/* 162 */ 1, "\242",
/* 163 */ 1, "\243",
/* 164 */ 1, "\244",
/* 165 */ 1, "\245",
/* 166 */ 1, "\246",
/* 167 */ 1, "\247",
/* 168 */ 1, "\250",
/* 169 */ 1, "\251",
/* 170 */ 1, "\252",
/* 171 */ 1, "\253",
/* 172 */ 1, "\254",
/* 173 */ 1, "\255",
/* 174 */ 1, "\256",
/* 175 */ 1, "\257",
/* 176 */ 1, "\260",
/* 177 */ 1, "\261",
/* 178 */ 1, "\262",
/* 179 */ 1, "\263",
/* 180 */ 1, "\264",
/* 181 */ 1, "\265",
/* 182 */ 1, "\266",
/* 183 */ 1, "\267",
/* 184 */ 1, "\270",
/* 185 */ 1, "\271",
/* 186 */ 1, "\272",
/* 187 */ 1, "\273",
/* 188 */ 1, "\274",
/* 189 */ 1, "\275",
/* 190 */ 1, "\276",
/* 191 */ 1, "\277",
/* 192 */ 1, "\300",
/* 193 */ 1, "\301",
/* 194 */ 1, "\302",
/* 195 */ 1, "\303",
/* 196 */ 1, "\304",
/* 197 */ 1, "\305",
/* 198 */ 1, "\306",
/* 199 */ 1, "\307",
/* 200 */ 1, "\310",
/* 201 */ 1, "\311",
/* 202 */ 1, "\312",
/* 203 */ 1, "\313",
/* 204 */ 1, "\314",
/* 205 */ 1, "\315",
/* 206 */ 1, "\316",
/* 207 */ 1, "\317",
/* 208 */ 1, "\320",
/* 209 */ 1, "\321",
/* 210 */ 1, "\322",
/* 211 */ 1, "\323",
/* 212 */ 1, "\324",
/* 213 */ 1, "\325",
/* 214 */ 1, "\326",
/* 215 */ 1, "\327",
/* 216 */ 1, "\330",
/* 217 */ 1, "\331",
/* 218 */ 1, "\332",
/* 219 */ 1, "\333",
/* 220 */ 1, "\334",
/* 221 */ 1, "\335",
/* 222 */ 1, "\336",
/* 223 */ 1, "\337",
/* 224 */ 1, "\340",
/* 225 */ 1, "\341",
/* 226 */ 1, "\342",
/* 227 */ 1, "\343",
/* 228 */ 1, "\344",
/* 229 */ 1, "\345",
/* 230 */ 1, "\346",
/* 231 */ 1, "\347",
/* 232 */ 1, "\350",
/* 233 */ 1, "\351",
/* 234 */ 1, "\352",
/* 235 */ 1, "\353",
/* 236 */ 1, "\354",
/* 237 */ 1, "\355",
/* 238 */ 1, "\356",
/* 239 */ 1, "\357",
/* 240 */ 1, "\360",
/* 241 */ 1, "\361",
/* 242 */ 1, "\362",
/* 243 */ 1, "\363",
/* 244 */ 1, "\364",
/* 245 */ 1, "\365",
/* 246 */ 1, "\366",
/* 247 */ 1, "\367",
/* 248 */ 1, "\370",
/* 249 */ 1, "\371",
/* 250 */ 1, "\372",
/* 251 */ 1, "\373",
/* 252 */ 1, "\374",
/* 253 */ 1, "\375",
/* 254 */ 1, "\376",
/* 255 */ 1, "\377"
#else
/* 160 */ 5, "[160]",
/* 161 */ 5, "[161]",
/* 162 */ 5, "[162]",
/* 163 */ 5, "[163]",
/* 164 */ 5, "[164]",
/* 165 */ 5, "[165]",
/* 166 */ 5, "[166]",
/* 167 */ 5, "[167]",
/* 168 */ 5, "[168]",
/* 169 */ 5, "[169]",
/* 170 */ 5, "[170]",
/* 171 */ 5, "[171]",
/* 172 */ 5, "[172]",
/* 173 */ 5, "[173]",
/* 174 */ 5, "[174]",
/* 175 */ 5, "[175]",
/* 176 */ 5, "[176]",
/* 177 */ 5, "[177]",
/* 178 */ 5, "[178]",
/* 179 */ 5, "[179]",
/* 180 */ 5, "[180]",
/* 181 */ 5, "[181]",
/* 182 */ 5, "[182]",
/* 183 */ 5, "[183]",
/* 184 */ 5, "[184]",
/* 185 */ 5, "[185]",
/* 186 */ 5, "[186]",
/* 187 */ 5, "[187]",
/* 188 */ 5, "[188]",
/* 189 */ 5, "[189]",
/* 190 */ 5, "[190]",
/* 191 */ 5, "[191]",
/* 192 */ 5, "[192]",
/* 193 */ 5, "[193]",
/* 194 */ 5, "[194]",
/* 195 */ 5, "[195]",
/* 196 */ 5, "[196]",
/* 197 */ 5, "[197]",
/* 198 */ 5, "[198]",
/* 199 */ 5, "[199]",
/* 200 */ 5, "[200]",
/* 201 */ 5, "[201]",
/* 202 */ 5, "[202]",
/* 203 */ 5, "[203]",
/* 204 */ 5, "[204]",
/* 205 */ 5, "[205]",
/* 206 */ 5, "[206]",
/* 207 */ 5, "[207]",
/* 208 */ 5, "[208]",
/* 209 */ 5, "[209]",
/* 210 */ 5, "[210]",
/* 211 */ 5, "[211]",
/* 212 */ 5, "[212]",
/* 213 */ 5, "[213]",
/* 214 */ 5, "[214]",
/* 215 */ 5, "[215]",
/* 216 */ 5, "[216]",
/* 217 */ 5, "[217]",
/* 218 */ 5, "[218]",
/* 219 */ 5, "[219]",
/* 220 */ 5, "[220]",
/* 221 */ 5, "[221]",
/* 222 */ 5, "[222]",
/* 223 */ 5, "[223]",
/* 224 */ 5, "[224]",
/* 225 */ 5, "[225]",
/* 226 */ 5, "[226]",
/* 227 */ 5, "[227]",
/* 228 */ 5, "[228]",
/* 229 */ 5, "[229]",
/* 230 */ 5, "[230]",
/* 231 */ 5, "[231]",
/* 232 */ 5, "[232]",
/* 233 */ 5, "[233]",
/* 234 */ 5, "[234]",
/* 235 */ 5, "[235]",
/* 236 */ 5, "[236]",
/* 237 */ 5, "[237]",
/* 238 */ 5, "[238]",
/* 239 */ 5, "[239]",
/* 240 */ 5, "[240]",
/* 241 */ 5, "[241]",
/* 242 */ 5, "[242]",
/* 243 */ 5, "[243]",
/* 244 */ 5, "[244]",
/* 245 */ 5, "[245]",
/* 246 */ 5, "[246]",
/* 247 */ 5, "[247]",
/* 248 */ 5, "[248]",
/* 249 */ 5, "[249]",
/* 250 */ 5, "[250]",
/* 251 */ 5, "[251]",
/* 252 */ 5, "[252]",
/* 253 */ 5, "[253]",
/* 254 */ 5, "[254]",
/* 255 */ 5, "[255]"
#endif
};
SHAR_EOF
cat << \SHAR_EOF > cmdline.c
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
#include "stevie.h"
static char *altfile = NULL; /* alternate file */
static int altline; /* line # in alternate file */
static char *nowrtmsg = "No write since last change (use ! to override)";
extern char **files; /* used for "n" and "rew" */
extern int curfile;
extern int numfiles;
/*
* The next two variables contain the bounds of any range given in a command.
* If no range was given, both contain null line pointers. If only a single
* line was given, u_pos will contain a null line pointer.
*/
static LPTR l_pos, u_pos;
static bool_t interactive; /* TRUE if we're reading a real command line */
static bool_t doecmd();
static void
badcmd(), doshell(), get_range();
static LPTR *get_line();
#ifdef MEGAMAX
overlay "cmdline"
#endif
/*
* readcmdline() - accept a command line starting with ':', '/', or '?'
*
* readcmdline() accepts and processes colon commands and searches. If 'cmdline'
* is null, the command line is read here. Otherwise, cmdline points to a
* complete command line that should be used. This is used in main() to
* handle initialization commands in the environment variable "EXINIT".
*/
void
readcmdline(firstc, cmdline)
char firstc; /* either ':', '/', or '?' */
char *cmdline; /* optional command string */
{
char c;
char buff[CMDBUFFSIZE];
char *p, *q, *cmd, *arg;
bool_t literal_next_flag = FALSE;
/*
* Clear the range variables.
*/
l_pos.linep = (LINE *) NULL;
u_pos.linep = (LINE *) NULL;
interactive = (cmdline == NULL);
if (interactive)
gotocmdline(YES, firstc);
p = buff;
if (firstc != ':')
*p++ = firstc;
if (interactive) {
/* collect the command string, handling '\b' and @ */
for (;;) {
c = vgetc();
if (c == CTRL('V') && !literal_next_flag) {
literal_next_flag = TRUE;
outchar('^');
continue;
}
if (c == '\n' || ((c == '\r' || c == ESC) && (!literal_next_flag)))
break;
if ((c == '\b') && (!literal_next_flag)) {
if (p > buff) {
p--;
/*
* this is gross, but it relies only on 'gotocmdline'
*/
gotocmdline(YES, firstc == ':' ? ':' : NUL);
for (q = buff; q < p; q++)
outstr(chars[*q].ch_str);
} else {
msg("");
return; /* back to cmd mode */
}
continue;
}
if ((c == '@') && (!literal_next_flag)) {
p = buff;
gotocmdline(YES, firstc);
continue;
}
if (literal_next_flag) {
literal_next_flag = FALSE;
outchar('\b');
}
outstr(chars[c].ch_str);
*p++ = c;
}
*p = '\0';
} else {
if (strlen(cmdline) > CMDBUFFSIZE - 2) /* should really do something
* better here... */
return;
strcpy(p, cmdline);
}
/* skip any initial white space */
for (cmd = buff; *cmd != NUL && isspace(*cmd); cmd++);
/* search commands */
c = *cmd;
if (c == '/' || c == '?') {
cmd++;
/* was the command was '//' or '??' (I.E. repeat last search) */
if ((*cmd == c) || (*cmd == NUL)) {
if (c == '/')
searchagain(FORWARD);
else
searchagain(BACKWARD);
return;
}
/* If there is a matching '/' or '?' at the end, toss it */
p = strchr(cmd, NUL);
if (*(p - 1) == c && *(p - 2) != '\\')
*(p - 1) = NUL;
dosearch((c == '/') ? FORWARD : BACKWARD, cmd);
return;
}
/*
* Parse a range, if present (and update the cmd pointer).
*/
get_range(&cmd);
/* isolate the command and find any argument */
for (p = cmd; *p != NUL && !isspace(*p); p++);
if (*p == NUL)
arg = NULL;
else {
*p = NUL;
for (p++; *p != NUL && isspace(*p); p++);
arg = p;
if (*arg == NUL)
arg = NULL;
}
if (strcmp(cmd, "q!") == 0)
getout(0);
if (strcmp(cmd, "q") == 0) {
if (Changed)
emsg(nowrtmsg);
else
getout(0);
return;
}
if (strcmp(cmd, "w") == 0) {
if (arg == NULL) {
if (Filename != NULL) {
writeit(Filename, &l_pos, &u_pos);
UNCHANGED;
} else
emsg("No output file");
} else
writeit(arg, &l_pos, &u_pos);
return;
}
if (strcmp(cmd, "wq") == 0) {
if (Filename != NULL) {
if (writeit(Filename, (LPTR *) NULL, (LPTR *) NULL))
getout(0);
} else
emsg("No output file");
return;
}
if (strcmp(cmd, "x") == 0) {
if (Changed) {
if (Filename != NULL) {
if (!writeit(Filename, (LPTR *) NULL, (LPTR *) NULL))
return;
} else {
emsg("No output file");
return;
}
}
getout(0);
}
if (strcmp(cmd, "f") == 0 && arg == NULL) {
fileinfo();
return;
}
if (*cmd == 'n') {
if ((curfile + 1) < numfiles) {
/*
* stuff ":e[!] FILE\n"
*/
stuffReadbuff(":e");
if (cmd[1] == '!')
stuffReadbuff("!");
stuffReadbuff(" ");
stuffReadbuff(files[++curfile]);
stuffReadbuff("\n");
} else
emsg("No more files!");
return;
}
if (*cmd == 'p') {
if (curfile > 0) {
/*
* stuff ":e[!] FILE\n"
*/
stuffReadbuff(":e");
if (cmd[1] == '!')
stuffReadbuff("!");
stuffReadbuff(" ");
stuffReadbuff(files[--curfile]);
stuffReadbuff("\n");
} else
emsg("No more files!");
return;
}
if (strncmp(cmd, "rew", 3) == 0) {
if (numfiles <= 1) /* nothing to rewind */
return;
curfile = 0;
/*
* stuff ":e[!] FILE\n"
*/
stuffReadbuff(":e");
if (cmd[3] == '!')
stuffReadbuff("!");
stuffReadbuff(" ");
stuffReadbuff(files[0]);
stuffReadbuff("\n");
return;
}
if (strcmp(cmd, "e") == 0 || strcmp(cmd, "e!") == 0) {
doecmd(arg, cmd[1] == '!');
return;
}
if (strcmp(cmd, "f") == 0) {
Filename = strsave(arg);
filemess("");
return;
}
if (strcmp(cmd, "r") == 0 || strcmp(cmd, ".r") == 0) {
if (arg == NULL) {
badcmd();
return;
}
if (readfile(arg, Curschar, 1)) {
emsg("Can't open file");
return;
}
updateNextscreen();
CHANGED;
return;
}
if (strcmp(cmd, ".=") == 0) {
smsg("line %d", cntllines(Filemem, Curschar));
return;
}
if (strcmp(cmd, "$=") == 0) {
smsg("%d", cntllines(Filemem, Fileend) - 1);
return;
}
if (strncmp(cmd, "ta", 2) == 0) {
dotag(arg, cmd[2] == '!');
return;
}
if (strcmp(cmd, "set") == 0) {
doset(arg, interactive);
return;
}
if (strcmp(cmd, "help") == 0) {
if (help()) {
screenclear();
updateNextscreen();
}
return;
}
if (strcmp(cmd, "version") == 0) {
extern char *Version;
msg(Version);
return;
}
if (strcmp(cmd, "sh") == 0) {
doshell();
return;
}
/*
* If we got a line, but no command, then go to the line.
*/
if (*cmd == NUL && l_pos.linep != NULL) {
*Curschar = l_pos;
cursupdate();
return;
}
badcmd();
}
/*
* get_range - parse a range specifier
*
* Ranges are of the form:
*
* addr[,addr]
*
* where 'addr' is:
*
* $ [+-NUM] 'x [+-NUM] (where x denotes a currently defined mark)
* . [+-NUM] NUM
*
* The pointer *cp is updated to point to the first character following the
* range spec. If an initial address is found, but no second, the upper bound
* is equal to the lower.
*/
static void
get_range(cp)
char **cp;
{
LPTR *l;
char *p;
if ((l = get_line(cp)) == NULL)
return;
l_pos = *l;
for (p = *cp; *p != NUL && isspace(*p); p++);
*cp = p;
if (*p != ',') { /* is there another line spec ? */
u_pos = l_pos;
return;
}
*cp = ++p;
if ((l = get_line(cp)) == NULL) {
u_pos = l_pos;
return;
}
u_pos = *l;
}
static LPTR *
get_line(cp)
char **cp;
{
static LPTR pos;
LPTR *lp;
char *p, c;
int lnum;
pos.index = 0; /* shouldn't matter... check back later */
p = *cp;
/*
* Determine the basic form, if present.
*/
switch (c = *p++) {
case '$':
pos.linep = Fileend->linep->prev;
break;
case '.':
pos.linep = Curschar->linep;
break;
case '\'':
if ((lp = getmark(*p++)) == NULL) {
emsg("Unknown mark");
return (LPTR *) NULL;
}
pos = *lp;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
for (lnum = c - '0'; isdigit(*p); p++)
lnum = (lnum * 10) + (*p - '0');
if (lnum == 0)
lnum = 1;
pos = *gotoline(lnum);
break;
default:
return (LPTR *) NULL;
}
while (*p != NUL && isspace(*p))
p++;
if (*p == '-' || *p == '+') {
bool_t neg = (*p++ == '-');
for (lnum = 0; isdigit(*p); p++)
lnum = (lnum * 10) + (*p - '0');
if (neg)
lnum = -lnum;
pos = *gotoline(cntllines(Filemem, &pos) + lnum);
}
*cp = p;
return &pos;
}
static void
badcmd()
{
if (interactive)
emsg("Unrecognized command");
}
/*
* dotag(tag, force) - goto tag
*/
void
dotag(tag, force)
char *tag;
bool_t force;
{
FILE *tp, *fopen();
char lbuf[LSIZE];
char *fname, *str;
if ((tp = fopen("tags", "r")) == NULL) {
emsg("Can't open tags file");
return;
}
while (fgets(lbuf, LSIZE, tp) != NULL) {
if ((fname = strchr(lbuf, TAB)) == NULL) {
emsg("Format error in tags file");
return;
}
*fname++ = '\0';
if ((str = strchr(fname, TAB)) == NULL) {
emsg("Format error in tags file");
return;
}
*str++ = '\0';
if (strcmp(lbuf, tag) == 0) {
if (doecmd(fname, force)) {
stuffReadbuff(str); /* str has \n at end */
stuffReadbuff("\007"); /* CTRL('G') */
fclose(tp);
return;
}
}
}
emsg("tag not found");
fclose(tp);
}
static bool_t
doecmd(arg, force)
char *arg;
bool_t force;
{
int line = 1; /* line # to go to in new file */
if (!force && Changed) {
emsg(nowrtmsg);
return FALSE;
}
if (arg != NULL) {
/*
* First detect a ":e" on the current file. This is mainly for ":ta"
* commands where the destination is within the current file.
*/
if (Filename != NULL && strcmp(arg, Filename) == 0) {
if (!Changed || (Changed && !force))
return TRUE;
}
if (strcmp(arg, "#") == 0) { /* alternate */
char *s = Filename;
if (altfile == NULL) {
emsg("No alternate file");
return FALSE;
}
Filename = altfile;
altfile = s;
line = altline;
altline = cntllines(Filemem, Curschar);
} else {
altfile = Filename;
altline = cntllines(Filemem, Curschar);
Filename = strsave(arg);
}
}
if (Filename == NULL) {
emsg("No filename");
return FALSE;
}
/* clear mem and read file */
freeall();
filealloc();
UNCHANGED;
readfile(Filename, Filemem, 0);
*Topchar = *Curschar;
if (line != 1) {
stuffnumReadbuff(line);
stuffReadbuff("G");
}
setpcmark();
updateNextscreen();
return TRUE;
}
static void
doshell()
{
char *sh, *getenv();
sh = getenv("SHELL");
if (sh == NULL) {
emsg("Shell variable not set");
return;
}
gotocmdline(YES, NUL);
if (system(sh) < 0) {
emsg("Exec failed");
return;
}
wait_return();
}
void
gotocmdline(clr, firstc)
bool_t clr;
char firstc;
{
windgoto(Rows - 1, 0);
if (clr)
outstr(T_EL); /* clear the bottom line */
if (firstc)
outchar(firstc);
}
/*
* msg(s) - displays the string 's' on the status line
*/
void
msg(s)
char *s;
{
gotocmdline(YES, NUL);
outstr(s);
#ifdef AMIGA
fflush(stdout);
#endif
#ifdef BSD
fflush(stdout);
#endif
}
/* VARARGS */
void
smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9)
char *s;
int a1, a2, a3, a4, a5, a6, a7, a8, a9;
{
char sbuf[MAX_COLUMNS + 1];
sprintf(sbuf, s, a1, a2, a3, a4, a5, a6, a7, a8, a9);
msg(sbuf);
}
/*
* emsg() - display an error message
*
* Rings the bell, if appropriate, and calls message() to do the real work
*/
void
emsg(s)
char *s;
{
UndoInProgress = FALSE;
RedrawingDisabled = FALSE;
ResetBuffers();
if (P(P_EB))
beep();
outstr(T_TI);
msg(s);
outstr(T_TP);
#ifdef AMIGA
fflush(stdout);
#endif
#ifdef BSD
fflush(stdout);
#endif
}
void
wait_return()
{
char c;
outstr("Press RETURN to continue");
do {
c = vgetc();
} while (c != '\r' && c != '\n');
screenclear();
updateNextscreen();
}
SHAR_EOF
cat << \SHAR_EOF > dec.c
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
#include "stevie.h"
/*
* dec(p)
*
* Decrement the line pointer 'p' crossing line boundaries as necessary. Return
* 1 when crossing a line, -1 when at start of file, 0 otherwise.
*/
int
dec(lp)
LPTR *lp;
{
if (lp->index > 0) { /* still within line */
lp->index--;
return 0;
}
if (lp->linep->prev != NULL) { /* there is a prior line */
lp->linep = lp->linep->prev;
lp->index = strlen(lp->linep->s);
return 1;
}
return -1; /* at start of file */
}
SHAR_EOF
cat << \SHAR_EOF > edit.c
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
#include "stevie.h"
/*
* This flag is used to make auto-indent work right on lines where only a
* <RETURN> or <ESC> is typed. It is set when an auto-indent is done, and
* reset when any other editting is done on the line. If an <ESC> or <RETURN>
* is received, and did_ai is TRUE, the line is truncated.
*/
bool_t did_ai = FALSE;
void
edit()
{
char c;
bool_t literal_next_flag = FALSE;
Prenum = 0;
/* position the display and the cursor at the top of the file. */
*Topchar = *Filemem;
*Curschar = *Filemem;
Cursrow = Curscol = 0;
for (;;) {
if (!RedrawingDisabled) {
cursupdate(); /* Figure out where the cursor is based on
* Curschar. */
if (MustRedrawLine)
redrawline();
if (MustRedrawScreen)
updateRealscreen();
windgoto(Cursrow, Curscol);
}
c = vgetc();
if (State == NORMAL) {
/* We're in the normal (non-insert) mode. */
/* Pick up any leading digits and compute 'Prenum' */
if ((Prenum > 0 && isdigit(c)) || (isdigit(c) && c != '0')) {
Prenum = Prenum * 10 + (c - '0');
continue;
}
/* execute the command */
normal(c);
Prenum = 0;
} else {
if (c == CTRL('V') && !literal_next_flag) {
literal_next_flag = TRUE;
outchar('^');
continue;
}
if (literal_next_flag) {
literal_next_flag = FALSE;
outchar('\b');
if (c != NL) {
did_ai = FALSE;
insertchar(c);
continue;
}
}
switch (c) { /* We're in insert mode */
case CR:
case NL:
*Insbuffptr++ = NL;
*Insbuffptr = NUL;
if (!opencmd(FORWARD, TRUE))
goto doESCkey; /* out of memory */
if (!RedrawingDisabled)
windgoto(Cursrow, Curscol);
break;
case ESC: /* an escape ends input mode */
doESCkey:
set_want_col = TRUE;
/* Don't end up on a '\n' if you can help it. */
if (gchar(Curschar) == NUL && Curschar->index != 0)
dec(Curschar);
/*
* The cursor should end up on the last inserted character.
* This is an attempt to match the real 'vi', but it may not
* be quite right yet.
*/
if (Curschar->index != 0 && !endofline(Curschar))
dec(Curschar);
State = NORMAL;
msg("");
if (!UndoInProgress) {
int n;
char *p;
if (last_command == 'o')
AppendToUndobuff(UNDO_SHIFTJ_STR);
if (Insbuff != Insbuffptr) {
if (last_command == 'O')
AppendToUndobuff("0");
AppendToRedobuff(Insbuff);
AppendToUndoUndobuff(Insbuff);
n = 0;
for (p = Insbuff; p < Insbuffptr; p++) {
if (*p == NL) {
if (n) {
AppendNumberToUndobuff(n);
AppendToUndobuff("dl");
n = 0;
}
AppendToUndobuff(UNDO_SHIFTJ_STR);
} else
n++;
}
if (n) {
AppendNumberToUndobuff(n);
AppendToUndobuff("dl");
}
}
if (last_command == 'c') {
AppendToUndobuff(mkstr(last_command_char));
AppendToUndobuff(Yankbuff);
AppendToUndobuff(ESC_STR);
}
AppendToRedobuff(ESC_STR);
AppendToUndoUndobuff(ESC_STR);
if (last_command == 'O')
AppendToUndobuff(UNDO_SHIFTJ_STR);
}
break;
case CTRL('D'):
/*
* Control-D is treated as a backspace in insert mode to make
* auto-indent easier. This isn't completely compatible with
* vi, but it's a lot easier than doing it exactly right, and
* the difference isn't very noticeable.
*/
case BS:
/* can't backup past starting point */
if (Curschar->linep == Insstart->linep &&
Curschar->index <= Insstart->index) {
beep();
break;
}
/* can't backup to a previous line */
if (Curschar->linep != Insstart->linep &&
Curschar->index <= 0) {
beep();
break;
}
did_ai = FALSE;
dec(Curschar);
delchar(TRUE, FALSE);
Insbuffptr--;
*Insbuffptr = NUL;
cursupdate();
updateline();
break;
default:
did_ai = FALSE;
insertchar(c);
break;
}
}
}
}
/*
* Special characters in this context are those that need processing other
* than the simple insertion that can be performed here. This includes ESC
* which terminates the insert, and CR/NL which need special processing to
* open up a new line. This routine tries to optimize insertions performed by
* the "redo" command, so it needs to know when it should stop and defer
* processing to the "normal" mechanism.
*/
#define ISSPECIAL(c) ((c) == NL || (c) == CR || (c) == ESC)
void
insertchar(c)
char c;
{
if (anyinput()) { /* If there's any pending input, grab it all
* at once. */
char *p;
p = Insbuffptr;
*Insbuffptr++ = c;
for (c = vpeekc(); !ISSPECIAL(c) && anyinput(); c = vpeekc()) {
c = vgetc();
*Insbuffptr++ = c;
/*
* The following kludge avoids overflowing the insert buffer.
*/
if (Insbuffptr + 10 >= &Insbuff[INSERT_SIZE]) {
int n;
*Insbuffptr = NUL;
insstr(p);
Insbuffptr = Insbuff;
p = Insbuffptr;
emsg("Insert buffer overflow - buffers flushed");
sleep(2);
n = cntllines(Filemem, Curschar);
AppendPositionToUndobuff(Curschar->index, n);
AppendPositionToUndoUndobuff(Curschar->index, n);
if (endofline(Curschar)) {
AppendToRedobuff("a");
AppendToUndoUndobuff("a");
} else {
AppendToRedobuff("i");
AppendToUndoUndobuff("i");
}
}
}
*Insbuffptr = NUL;
insstr(p);
} else {
inschar(c);
*Insbuffptr++ = c;
/*
* The following kludge avoids overflowing the insert buffer.
*/
if (Insbuffptr + 10 >= &Insbuff[INSERT_SIZE]) {
int n;
Insbuffptr = Insbuff;
emsg("Insert buffer overflow - buffers flushed");
sleep(2);
n = cntllines(Filemem, Curschar);
AppendPositionToUndobuff(Curschar->index, n);
AppendPositionToUndoUndobuff(Curschar->index, n);
if (endofline(Curschar)) {
AppendToRedobuff("a");
AppendToUndoUndobuff("a");
} else {
AppendToRedobuff("i");
AppendToUndoUndobuff("i");
}
}
*Insbuffptr = NUL;
}
updateline();
}
void
getout(r)
int r;
{
windgoto(Rows - 1, 0);
putchar('\r');
putchar('\n');
windexit(r);
}
void
scrolldown(nlines)
int nlines;
{
LPTR *p;
int done = 0; /* total # of physical lines done */
/* Scroll up 'nlines' lines. */
while (nlines--) {
if ((p = prevline(Topchar)) == NULL)
break;
done += plines(p);
*Topchar = *p;
if (Curschar->linep == Botchar->linep->prev)
*Curschar = *prevline(Curschar);
}
s_ins(0, done);
}
void
scrollup(nlines)
int nlines;
{
LPTR *p;
int done = 0; /* total # of physical lines done */
int pl; /* # of plines for the current line */
/* Scroll down 'nlines' lines. */
while (nlines--) {
pl = plines(Topchar);
if ((p = nextline(Topchar)) == NULL)
break;
done += pl;
if (Curschar->linep == Topchar->linep)
*Curschar = *p;
*Topchar = *p;
}
s_del(0, done);
}
/*
* oneright oneleft onedown oneup
*
* Move one char {right,left,down,up}. Return TRUE when sucessful, FALSE when
* we hit a boundary (of a line, or the file).
*/
bool_t
oneright()
{
set_want_col = TRUE;
switch (inc(Curschar)) {
case 0:
return TRUE;
case 1:
dec(Curschar); /* crossed a line, so back up */
/* FALLTHROUGH */
case -1:
return FALSE;
}
return FALSE; /* PARANOIA: should never reach here */
}
bool_t
oneleft()
{
set_want_col = TRUE;
switch (dec(Curschar)) {
case 0:
return TRUE;
case 1:
inc(Curschar); /* crossed a line, so back up */
/* FALLTHROUGH */
case -1:
return FALSE;
}
return FALSE; /* PARANOIA: should never reach here */
}
void
beginline(flag)
bool_t flag;
{
while (oneleft());
if (flag) {
while (isspace(gchar(Curschar)) && oneright());
}
set_want_col = TRUE;
}
bool_t
oneup(n)
{
LPTR p, *np;
int k;
p = *Curschar;
for (k = 0; k < n; k++) {
/* Look for the previous line */
if ((np = prevline(&p)) == NULL) {
/* If we've at least backed up a little .. */
if (k > 0)
break; /* to update the cursor, etc. */
else
return FALSE;
}
p = *np;
}
*Curschar = p;
cursupdate(); /* make sure Topchar is valid */
/* try to advance to the column we want to be at */
*Curschar = *coladvance(&p, Curswant);
return TRUE;
}
bool_t
onedown(n)
{
LPTR p, *np;
int k;
p = *Curschar;
for (k = 0; k < n; k++) {
/* Look for the next line */
if ((np = nextline(&p)) == NULL) {
if (k > 0)
break;
else
return FALSE;
}
p = *np;
}
cursupdate(); /* make sure Topchar is valid */
/* try to advance to the column we want to be at */
*Curschar = *coladvance(&p, Curswant);
return TRUE;
}
SHAR_EOF
cat << \SHAR_EOF > fileio.c
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
#include "stevie.h"
void
filemess(s)
char *s;
{
sprintf(IObuff, "\"%s\" %s", ((Filename == NULL) ? "" : Filename), s);
msg(IObuff);
}
void
renum()
{
LPTR *p;
unsigned int l = 0;
for (p = Filemem; p != NULL; p = nextline(p), l += LINEINC)
p->linep->num = l;
Fileend->linep->num = 0xffff;
}
#ifdef MEGAMAX
overlay "fileio"
#endif
bool_t
readfile(fname, fromp, nochangename)
char *fname;
LPTR *fromp;
bool_t nochangename; /* if TRUE, don't change the Filename */
{
FILE *f, *fopen();
LINE *curr;
char *p;
int i, c;
long nchars;
int unprint = 0;
int linecnt = 0;
bool_t wasempty = bufempty();
curr = fromp->linep;
if (!nochangename)
Filename = strsave(fname);
if ((f = fopen(fname, "r")) == NULL)
return TRUE;
filemess("");
i = 0;
for (nchars = 0; (c = getc(f)) != EOF; nchars++) {
if (c >= 0x80) {
c -= 0x80;
unprint++;
}
/*
* Nulls are special, so they can't show up in the file. We should
* count nulls seperate from other nasties, but this is okay for now.
*/
if (c == NUL) {
unprint++;
continue;
}
if (c == '\n') { /* process the completed line */
int len;
LINE *lp;
IObuff[i] = NUL;
len = strlen(IObuff) + 1;
if ((lp = newline(len)) == NULL) {
fprintf(stderr, "not enough memory - should never happen");
getout(1);
}
strcpy(lp->s, IObuff);
curr->next->prev = lp; /* new line to next one */
lp->next = curr->next;
curr->next = lp; /* new line to prior one */
lp->prev = curr;
curr = lp; /* new line becomes current */
i = 0;
linecnt++;
} else
IObuff[i++] = (char) c;
}
fclose(f);
/*
* If the buffer was empty when we started, we have to go back and remove
* the "dummy" line at Filemem and patch up the ptrs.
*/
if (wasempty) {
LINE *dummy = Filemem->linep; /* dummy line ptr */
free(dummy->s); /* free string space */
Filemem->linep = Filemem->linep->next;
free((char *) dummy); /* free LINE struct */
Filemem->linep->prev = NULL;
Curschar->linep = Filemem->linep;
Topchar->linep = Filemem->linep;
}
if (unprint > 0)
p = "\"%s\" %d lines, %ld characters (%d un-printable))";
else
p = "\"%s\" %d lines, %ld characters";
sprintf(IObuff, p, fname, linecnt, nchars, unprint);
msg(IObuff);
renum();
return FALSE;
}
/*
* writeit - write to file 'fname' lines 'start' through 'end'
*
* If either 'start' or 'end' contain null line pointers, the default is to use
* the start or end of the file respectively.
*/
bool_t
writeit(fname, start, end)
char *fname;
LPTR *start, *end;
{
FILE *f, *fopen();
FILE *fopenb(); /* open in binary mode, where needed */
char backup[16], *s;
long nchars;
int lines;
LPTR *p;
sprintf(IObuff, "\"%s\"", fname);
msg(IObuff);
/*
* Form the backup file name - change foo.* to foo.bak
*/
strcpy(backup, fname);
for (s = backup; *s && *s != '.'; s++);
*s = NUL;
strcat(backup, ".bak");
/*
* Delete any existing backup and move the current version to the backup.
* For safety, we don't remove the backup until the write has finished
* successfully. And if the 'backup' option is set, leave it around.
*/
rename(fname, backup);
f = P(P_CR) ? fopen(fname, "w") : fopenb(fname, "w");
if (f == NULL) {
emsg("Can't open file for writing!");
return FALSE;
}
/*
* If we were given a bound, start there. Otherwise just start at the
* beginning of the file.
*/
if (start == NULL || start->linep == NULL)
p = Filemem;
else
p = start;
lines = 0;
nchars = 0;
do {
fprintf(f, "%s\n", p->linep->s);
nchars += strlen(p->linep->s) + 1;
lines++;
/*
* If we were given an upper bound, and we just did that line, then
* bag it now.
*/
if (end != NULL && end->linep != NULL) {
if (end->linep == p->linep)
break;
}
} while ((p = nextline(p)) != NULL);
fclose(f);
sprintf(IObuff, "\"%s\" %d lines, %ld characters", fname, lines, nchars);
msg(IObuff);
UNCHANGED;
/*
* Remove the backup unless they want it left around
*/
if (!P(P_BK))
remove(backup);
return TRUE;
}
SHAR_EOF
cat << \SHAR_EOF > help.c
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
#include "stevie.h"
char *Version = "STEVIE - Version 3.10a";
static int helprow;
#ifdef HELP
#ifdef MEGAMAX
overlay "help"
#endif
static void longline();
bool_t
help()
{
/***********************************************************************
* First Screen: Positioning within file, Adjusting the Screen
***********************************************************************/
outstr(T_ED);
windgoto(helprow = 0, 0);
longline("\
Positioning within file\n\
=======================\n\
^F Forward screenfull Worked on by:\n\
^B Backward screenfull Tim Thompson\n");
longline("\
^D scroll down half screen Tony Andrews\n\
^U scroll up half screen G.R. (Fred) Walter\n");
longline("\
G Goto line (end default)\n\
]] next function\n\
[[ previous function\n\
/re next occurence of regular expression 're'\n");
longline("\
?re prior occurence of regular expression 're'\n\
n repeat last / or ?\n\
N reverse last / or ?\n\
% find matching (, ), {, }, [, or ]\n");
longline("\
\n\
Adjusting the screen\n\
====================\n\
^L Redraw the screen\n\
^E scroll window down 1 line\n\
^Y scroll window up 1 line\n");
longline("\
z<RETURN> redraw, current line at top\n\
z- ... at bottom\n\
z. ... at center\n");
windgoto(0, 52);
longline(Version);
windgoto(helprow = Rows - 2, 47);
longline("<Press space bar to continue>\n");
windgoto(helprow = Rows - 1, 47);
longline("<Any other key will quit>");
if (vgetc() != ' ')
return TRUE;
/***********************************************************************
* Second Screen: Character positioning
***********************************************************************/
outstr(T_ED);
windgoto(helprow = 0, 0);
longline("\
Character Positioning\n\
=====================\n\
^ first non-white\n\
0 beginning of line\n\
$ end of line\n\
h backward\n");
longline("\
l forward\n\
^H same as h\n\
space same as l\n\
fx find 'x' forward\n");
longline("\
Fx find 'x' backward\n\
tx upto 'x' forward\n\
Tx upto 'x' backward\n\
; Repeat last f, F, t, or T\n");
longline("\
, inverse of ;\n\
| to specified column\n\
% find matching (, ), {, }, [, or ]\n");
windgoto(helprow = Rows - 2, 47);
longline("<Press space bar to continue>\n");
windgoto(helprow = Rows - 1, 47);
longline("<Any other key will quit>");
if (vgetc() != ' ')
return TRUE;
/***********************************************************************
* Third Screen: Line Positioning, Marking and Returning
***********************************************************************/
outstr(T_ED);
windgoto(helprow = 0, 0);
longline("\
Line Positioning\n\
=====================\n\
H home window line\n\
L last window line\n\
M middle window line\n");
longline("\
+ next line, at first non-white\n\
- previous line, at first non-white\n\
CR return, same as +\n\
j next line, same column\n\
k previous line, same column\n");
longline("\
\n\
Marking and Returning\n\
=====================\n\
`` previous context\n\
'' ... at first non-white in line\n");
longline("\
mx mark position with letter 'x'\n\
`x to mark 'x'\n\
'x ... at first non-white in line\n");
windgoto(helprow = Rows - 2, 47);
longline("<Press space bar to continue>\n");
windgoto(helprow = Rows - 1, 47);
longline("<Any other key will quit>");
if (vgetc() != ' ')
return TRUE;
/***********************************************************************
* Fourth Screen: Insert & Replace,
***********************************************************************/
outstr(T_ED);
windgoto(helprow = 0, 0);
longline("\
Insert and Replace\n\
==================\n\
a append after cursor\n\
i insert before cursor\n\
A append at end of line\n\
I insert before first non-blank\n");
longline("\
o open line below\n\
O open line above\n\
rx replace single char with 'x'\n\
R replace characters (not yet)\n\
~ replace character under cursor with other case\n");
longline("\
\n\
Words, sentences, paragraphs\n\
============================\n\
w word forward\n\
b back word\n\
e end of word\n\
) to next sentence (not yet)\n\
} to next paragraph (not yet)\n");
longline("\
( back sentence (not yet)\n\
{ back paragraph (not yet)\n\
W blank delimited word\n\
B back W\n\
E to end of W");
windgoto(helprow = Rows - 2, 47);
longline("<Press space bar to continue>\n");
windgoto(helprow = Rows - 1, 47);
longline("<Any other key will quit>");
if (vgetc() != ' ')
return TRUE;
/***********************************************************************
* Fifth Screen: Misc. operations,
***********************************************************************/
outstr(T_ED);
windgoto(helprow = 0, 0);
longline("\
Undo & Redo\n\
=============\n\
u undo last change\n\
U restore current line (not yet)\n\
. repeat last change\n");
longline("\
\n\
File manipulation\n\
=================\n");
longline("\
:w write back changes\n\
:wq write and quit\n\
:x write if modified, and quit\n\
:q quit\n\
:q! quit, discard changes\n\
:e name edit file 'name'\n");
longline("\
:e! reedit, discard changes\n\
:e # edit alternate file\n\
:w name write file 'name'\n");
longline("\
:n edit next file in arglist\n\
:n args specify new arglist (not yet)\n\
:rew rewind arglist\n\
:f show current file and lines\n");
longline("\
:f file change current file name\n\
:ta tag to tag file entry 'tag'\n\
^] :ta, current word is tag");
windgoto(helprow = Rows - 2, 47);
longline("<Press space bar to continue>\n");
windgoto(helprow = Rows - 1, 47);
longline("<Any other key will quit>");
if (vgetc() != ' ')
return TRUE;
/***********************************************************************
* Sixth Screen: Operators, Misc. operations, Yank & Put
***********************************************************************/
outstr(T_ED);
windgoto(helprow = 0, 0);
longline("\
Operators (double to affect lines)\n\
==================================\n\
d delete\n\
c change\n");
longline("\
< left shift\n\
> right shift\n\
y yank to buffer\n");
longline("\n\
Miscellaneous operations\n\
========================\n\
C change rest of line\n\
D delete rest of line\n\
s substitute chars\n");
longline("\
S substitute lines (not yet)\n\
J join lines\n\
x delete characters\n\
X ... before cursor\n");
longline("\n\
Yank and Put\n\
============\n\
p put back text\n\
P put before\n\
Y yank lines");
windgoto(helprow = Rows - 1, 47);
longline("<Press any key>");
vgetc();
return TRUE;
}
static void
longline(p)
char *p;
{
# ifdef AMIGA
outstr(p);
# else
char *s;
for (s = p; *s; s++) {
if (*s == '\n')
windgoto(++helprow, 0);
else
outchar(*s);
}
# endif
}
#else
bool_t
help()
{
msg("Sorry, help not configured");
return FALSE;
}
#endif
SHAR_EOF
cat << \SHAR_EOF > inc.c
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
#include "stevie.h"
/*
* inc(p)
*
* Increment the line pointer 'p' crossing line boundaries as necessary. Return
* 1 when crossing a line, -1 when at end of file, 0 otherwise.
*/
int
inc(lp)
LPTR *lp;
{
char *p = &(lp->linep->s[lp->index]);
if (*p != NUL) { /* still within line */
lp->index++;
return ((p[1] != NUL) ? 0 : 1);
}
if (lp->linep->next != Fileend->linep) { /* there is a next line */
lp->index = 0;
lp->linep = lp->linep->next;
return 1;
}
return -1;
}
SHAR_EOF
# End of shell archive
exit 0
--
Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
Have five nice days.